package cn.edu.zut.score.service.impl;

import cn.edu.zut.score.core.cache.RedisCache;
import cn.edu.zut.score.core.constant.GroupTypeEnum;
import cn.edu.zut.score.core.convert.GroupConvert;
import cn.edu.zut.score.core.domain.PageResponse;
import cn.edu.zut.score.core.domain.RestResponse;
import cn.edu.zut.score.core.dto.request.GroupAddRequest;
import cn.edu.zut.score.core.dto.request.GroupPageRequest;
import cn.edu.zut.score.core.dto.response.GroupResponse;
import cn.edu.zut.score.core.entity.Group;
import cn.edu.zut.score.core.entity.GroupInfo;
import cn.edu.zut.score.core.entity.Info;
import cn.edu.zut.score.mapper.GroupMapper;
import cn.edu.zut.score.service.IGroupInfoService;
import cn.edu.zut.score.service.IGroupService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author zby
 * @since 2021-06-25
 */
@Slf4j
@Service
public class GroupServiceImpl extends ServiceImpl<GroupMapper, Group> implements IGroupService {

    @Autowired(required = false)
    private HttpServletRequest httpServletRequest;

    @Autowired
    private RedisCache redisCache;

    @Autowired(required = false)
    private GroupMapper groupMapper;

    @Autowired
    private IGroupInfoService iGroupInfoService;

    @Override
    public RestResponse<GroupResponse> saveGroup(GroupAddRequest groupAddRequest) {
        Group group = groupMapper.selectById(groupAddRequest.getId());
        if (group == null) {
            group = new Group();
            group.setName(groupAddRequest.getName());
            group.setType(groupAddRequest.getType());
            group.setCount(1);
            group.fillCreateInfo(httpServletRequest, redisCache);
            this.saveOrUpdate(group);
            log.info("新建小组ID：{}", group.getId());
        } else {
            group.setCount(group.getCount() + 1);
            group.fillUpdateInfo(httpServletRequest, redisCache);
            this.saveOrUpdate(group);
            log.info("小组ID{}人数加一", group.getId());
        }
        GroupInfo groupInfo = new GroupInfo();
        groupInfo.setGroupId(group.getId());
        groupInfo.setUserId(groupAddRequest.getNumberId());
        groupInfo.setType(groupAddRequest.getNumberType());
        groupInfo.fillCreateInfo(httpServletRequest, redisCache);
        iGroupInfoService.saveOrUpdate(groupInfo);
        log.info("插入小组成员ID:{}", groupInfo.getId());
        GroupResponse groupResponse = GroupConvert.INSTANCE.group2Response(group);
        List<Info> groupNumbers = iGroupInfoService.getGroupNumbers(group.getId());
        groupResponse.setCount(groupNumbers.size());
        groupResponse.setMembers(groupNumbers);
        return RestResponse.success(groupResponse);
    }

    @Override
    public RestResponse<GroupResponse> removeGroupNumber(GroupAddRequest groupAddRequest) {
        Group group = groupMapper.selectById(groupAddRequest.getId());
        group.setCount(group.getCount() - 1);
        this.saveOrUpdate(group);
        log.info("小组ID{}人数减一", group.getId());
        LambdaQueryWrapper<GroupInfo> qw = new LambdaQueryWrapper<>();
        qw.eq(GroupInfo::getGroupId, groupAddRequest.getId());
        qw.eq(GroupInfo::getUserId, groupAddRequest.getNumberId());
        iGroupInfoService.remove(qw);
        GroupResponse groupResponse = GroupConvert.INSTANCE.group2Response(group);
        List<Info> groupNumbers = iGroupInfoService.getGroupNumbers(group.getId());
        groupResponse.setCount(groupNumbers.size());
        groupResponse.setMembers(groupNumbers);
        return RestResponse.success(groupResponse);
    }

    @Override
    public RestResponse<Long> removeGroup(Long groupid) {
        iGroupInfoService.removeByGroupId(groupid);
        this.removeById(groupid);
        return RestResponse.success(groupid);
    }

    @Override
    public RestResponse<Integer> removeGroupsById(List<Long> allGroupIds) {
        Integer sum = 0;
        for (Long id : allGroupIds) {
            if (iGroupInfoService.removeByGroupId(id) > 0 && groupMapper.deleteById(id) > 0) {
                sum++;
                log.info("成功解散小组{}", id);
            }
        }
        return RestResponse.success(sum);
    }

    @Override
    public RestResponse<GroupResponse> getGroupById(Long groupid) {
        Group group = groupMapper.selectById(groupid);
        GroupResponse groupResponse = GroupConvert.INSTANCE.group2Response(group);
        LambdaQueryWrapper<GroupInfo> qw = new LambdaQueryWrapper<>();
        qw.eq(GroupInfo::getGroupId, groupid);
        qw.orderByAsc(GroupInfo::getType, GroupInfo::getId);
        List<Info> groupNumbers = iGroupInfoService.getGroupNumbers(group.getId());
        groupResponse.setMembers(groupNumbers);
        return RestResponse.success(groupResponse);
    }

    @Override
    public List<Info> getGroupsByIds(List<Long> ids) {
        LambdaQueryWrapper<Group> qw = new LambdaQueryWrapper<>();
        qw.in(Group::getId, ids);
        List<Group> groups = groupMapper.selectList(qw);
        return GroupConvert.INSTANCE.groups2Infos(groups);
    }

    @Override
    public RestResponse<PageResponse<GroupResponse>> getGroups(GroupPageRequest groupPageRequest) {
        Page<Group> page = new Page<>(groupPageRequest.getPage(), groupPageRequest.getLimit());
        LambdaQueryWrapper<Group> qw = new LambdaQueryWrapper<>();
        if (groupPageRequest.getLeaderId() != null && !groupPageRequest.getLeaderId().equals(0L)) {
            LambdaQueryWrapper<GroupInfo> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(GroupInfo::getUserId, groupPageRequest.getLeaderId());
            queryWrapper.orderByAsc(GroupInfo::getId);
            List<Long> ids = iGroupInfoService.list(queryWrapper).stream().map(GroupInfo::getGroupId).collect(Collectors.toList());
            //ids为以此教师为组长的所有小组ID
            if (ids.size() == 0) {
                //为0说明没有这样的小组，得让它查不到
                qw.eq(Group::getId, -1);
            } else {
                qw.in(Group::getId, ids);
            }
        }
        if (groupPageRequest.getType() != null && groupPageRequest.getType() != -1) {
            qw.eq(Group::getType, groupPageRequest.getType());
        }
        if (groupPageRequest.getCount() != null && groupPageRequest.getCount() != 0) {
            qw.eq(Group::getCount, groupPageRequest.getCount());
        }
        qw.ne(Group::getType, GroupTypeEnum.person.getCode());
        qw.orderByAsc(Group::getId);
        IPage<Group> pageData = groupMapper.selectPage(page, qw);
        List<Group> records = pageData.getRecords();
        List<GroupResponse> groupResponses = GroupConvert.INSTANCE.groups2Responses(records);
        for (GroupResponse groupResponse : groupResponses) {
            groupResponse.setType(GroupTypeEnum.getTypeByCode(Integer.valueOf(groupResponse.getType())));
            List<Info> groupNumbers = iGroupInfoService.getGroupNumbers(groupResponse.getId());
            groupResponse.setMembers(groupNumbers);
        }
        return RestResponse.success(new PageResponse<>(groupResponses, pageData.getTotal(), groupPageRequest.getPage(), groupPageRequest.getLimit()));
    }

    @Override
    public RestResponse<List<Info>> queryAllGroups() {
        return RestResponse.success(groupMapper.queryGroupsByType(GroupTypeEnum.person.getCode()));
    }
}
